//
//  ViewController.m
//  NSRunTimeDemo
//
//  Created by CPZX010 on 16/9/21.
//  Copyright © 2016年 谢昆鹏. All rights reserved.
//

#import "ViewController.h"
#import <objc/runtime.h>
#import <objc/message.h>
#import <objc/runtime.h>
#import <objc/objc.h>
#import "Person.h"
#import "NSObject+objName.h"
#import "Boy.h"


///作用:忽略因为没有声明而报的警告
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"


@interface ViewController ()

@property (weak, nonatomic) IBOutlet UIImageView *myImage;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    Class class1 = NSClassFromString(@"Boy");
    Person *person1 = [[Person alloc] init];
    Boy *boy1 = [[Boy alloc] init];
    //KVC方式--如果有系统保留字需要单独处理
    [boy1 setValuesForKeysWithDictionary:person1.paraDic];
    NSLog(@"%@___+++++++++++++++", boy1.dicKey);
    
    Boy *boy2 = [Boy runtimeObjectExchangeWithDic:person1.paraRuntimeDic];
    
    NSLog(@"%@___+++++++++++++++", boy2.dicKey);
    
    
    
    
    // Do any additional setup after loading the view, typically from a nib.
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
- (IBAction)jump:(id)sender {
    Person *person1 = [[Person alloc] init];
#pragma mark    1:发送消息
    //1:发送消息----->unrecognized selector sent to instance 来源
    /**注意注册发送消息是需要的设置 
     Enable Strict Checking of objc_msgSend Calls = NO;*/
    objc_msgSend(person1, @selector(eatSomething));
#pragma mark    2:动态交换方法
    //2:动态交换方法----->用途:重写系统方法
    //实际方法实现已经变换--会一直变换
    [person1 eatSomething];
    
#pragma mark    3:为person类动态添加方法
    //3:为person类动态添加方法-------->某种程度节约内存
    Class class = NSClassFromString(@"person");
    id personX = [[class alloc] init];
    [personX performSelector:@selector(running)];
//    [person1 performSelector:@selector(personEat)];
#pragma mark    4:为类目添加属性
    //4:为类目添加属性--------->动态添加属性
    NSObject *objc = [[NSObject alloc] init];
    objc.objcName = @"Object的属性name";
    NSLog(@"%@_+_+", objc.objcName);
    
#pragma mark    4:为类目添加属性
    //5:利用Runtime字典转化模型---------->高效率封装对象
    /**
     字典转换模型可以使用:KVC, Runtime动态转换----------->不论是直接用KVC还是用Runtime都有同样的弊端:即key找不到的问题;
     */
    

         
    
#pragma mark    6:动态创建类
    ///备用字典----->假设是后台推送来的的消息
    NSDictionary *getDic = @{@"propertys" : @{@"selfTitle" : @"动态创建类测试"},
                            @"getClass" : @"TestViewController"};
    

    //6:动态创建类-------->(用途:万能跳转, 推送消息<例如与服务器约定好,发送回来数据包含一个类的名字.则可以动态检测创建>)
    NSString *testClass = getDic[@"getClass"];
    const char *className = [testClass cStringUsingEncoding:NSASCIIStringEncoding];
    //使用字符串动态创建类
    Class newClass = objc_getClass(className);
    if (!newClass) {
        //创建一个类
        Class superClass = [NSObject class];
        newClass = objc_allocateClassPair(superClass, className, 0);
        //注册所创建的类
        objc_registerClassPair(newClass);
    }
    //创建对象
    id instance = [[newClass alloc] init];
    ///对该对象进行属性赋值
    [getDic[@"propertys"] enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
        unsigned int outCount = 0;
        Ivar *invarList = class_copyIvarList(newClass, &outCount);
        for (int i = 0; i < outCount; i ++) {
            Ivar ivar = invarList[i];
            NSString *name = [NSString stringWithUTF8String:ivar_getName(ivar)];
            NSString *propertyKey = [name substringFromIndex:1];
            if ([propertyKey isEqualToString:key]) {
                //如果包含当前属性, 则KVC------->没有使用三级判断,简单的一层对象
                [instance setValue:obj forKey:key];
            }
        }
    }];
    
//    UINavigationController *navC  = (UINavigationController *)self.navigationController;
    [self.navigationController pushViewController:instance animated:YES];
    
    
#pragma mark    7:动态改变其他类的方法(重写系统方法)
    //7:动态改变其他类的方法(重写系统方法)
    [person1 printNUM:10];
    
    
    
    
    
}


//- (void)forwardInvocation:(NSInvocation *)anInvocation {
//    [super forwardInvocation:anInvocation];
//}


@end
























